How to solve javax.net.ssl.SSLHandshakeException Error?
Asked Answered
B

5

126

I connected with VPN to setup the inventory API to get product list and it works fine. Once I get the result from the web-service and i bind to UI. And also I integrated PayPal with my application for make Express checkout when I make a call for payment I'm facing this error. I use servlet for back-end process. Can any one say how to fix this issue?

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Braddock answered 12/7, 2011 at 4:3 Comment(1)
what I would like to know, which exact target was in thath case... You get an exception, but you get no information about target, which might be different of what you expect.. I have such case, I am sure my link has certificate, and I am still getting this exceptionHiroko
O
183

First, you need to obtain the public certificate from the server you're trying to connect to. That can be done in a variety of ways, such as contacting the server admin and asking for it, using OpenSSL to download it, or, since this appears to be an HTTP server, connecting to it with any browser, viewing the page's security info, and saving a copy of the certificate. (Google should be able to tell you exactly what to do for your specific browser.)

Now that you have the certificate saved in a file, you need to add it to your JVM's trust store. At $JAVA_HOME/jre/lib/security/ for JREs or $JAVA_HOME/lib/security for JDKs, there's a file named cacerts, which comes with Java and contains the public certificates of the well-known Certifying Authorities. To import the new cert, run keytool as a user who has permission to write to cacerts:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

It will most likely ask you for a password. The default password as shipped with Java is changeit. Almost nobody changes it. After you complete these relatively simple steps, you'll be communicating securely and with the assurance that you're talking to the right server and only the right server (as long as they don't lose their private key).

Ocieock answered 19/7, 2011 at 4:8 Comment(10)
I'll need a little more detail than "not working". Try updating your question with what you've tried and some error output. Unfortunately, it's way past my bedtime, so maybe someone else will be able to answer your questions. This also is a very common situation. You can find lots of information on it online, including the keytool docs.Ocieock
Basically i need to include PayPal cert. I did your steps and cert also added in the appropriate location. then i run the app it say same error?Hiragana
Actually it works well no problem browser and I connected VPN to get inventory list at that time i make payment with PayPal, it say's SSL error but i use offline data or hot coded data means it works.Hiragana
@selladurai: You shouldn't need to import a cert for paypal. Unless your cacerts file has been corrupted or modified, it should contain all the trusted root certificates, and paypal's cert should be able to be traced back to one of those. You might try getting a copy of cacerts that you know is good and trying that one instead. If the problem persists, then you may not actually be connecting to paypal.Ocieock
@RyanStewart do I need to import it to glassfish somehow ? Because I did add the .cer file to my cacert in my java home directory but glassfish doesn't seem to use it so I'm still getting the error.Venerable
How does this work for distributing the application. Wouldn't it be really non-user friendly to have to go through all these steps? Or would you package a jdk with it already all setup?Guard
@RyanStewart any idea abt #38911075Rinarinaldi
It works! This is exactly what I need to do in order to enable my Java webservices to call a remote SSL endpoint. I was concentrating on adding the certificate to Tomcat; when in fact, the certificate should be added to JDK/JRE security instead. Now I understand.Ase
This solution worked to me: https://mcmap.net/q/35963/-resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatorexception-pkix-path-building-failed-errorCurrajong
Works in intellij following those steps, but I wonder when the jar is generated and then sent to production it will have the certificates too? whats the thing to do for that?Deformation
C
14

Whenever we are trying to connect to URL,

if server at the other site is running on https protocol and is mandating that we should communicate via information provided in certificate then we have following option:

1) ask for the certificate(download the certificate), import this certificate in trustore. Default trustore java uses can be found in \Java\jdk1.6.0_29\jre\lib\security\cacerts, then if we retry to connect to the URL connection would be accepted.

2) In normal business cases, we might be connecting to internal URLS in organizations and we know that they are correct. In such cases, you trust that it is the correct URL, In such cases above, code can be used which will not mandate to store the certificate to connect to particular URL.

for the point no 2 we have to follow below steps :

1) write below method which sets HostnameVerifier for HttpsURLConnection which returns true for all cases meaning we are trusting the trustStore.

  // trusting all certificate 
 public void doTrustToCertificates() throws Exception {
        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                    System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }

2) write below method, which calls doTrustToCertificates before trying to connect to URL

    // connecting to URL
    public void connectToUrl(){
     doTrustToCertificates();//  
     URL url = new URL("https://www.example.com");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
     System.out.println("ResponseCode ="+conn.getResponseCode());
   }

This call will return response code = 200 means connection is successful.

For more detail and sample example you can refer to URL.

Cyclist answered 20/3, 2014 at 5:54 Comment(1)
Google Play store will reject this. They will see that you are ignoring X509Certificate during the APK scan.Trocki
Q
0

I believe that you are trying to connect to a something using SSL but that something is providing a certificate which is not verified by root certification authorities such as verisign.. In essence by default secure connections can only be established if the person trying to connect knows the counterparties keys or some other verndor such as verisign can step in and say that the public key being provided is indeed right..

ALL OS's trust a handful of certification authorities and smaller certificate issuers need to be certified by one of the large certifiers making a chain of certifiers if you get what I mean...

Anyways coming back to the point.. I had a similiar problem when programming a java applet and a java server ( Hopefully some day I will write a complete blogpost about how I got all the security to work :) )

In essence what I had to do was to extract the public keys from the server and store it in a keystore inside my applet and when I connected to the server I used this key store to create a trust factory and that trust factory to create the ssl connection. There are alterante procedures as well such as adding the key to the JVM's trusted host and modifying the default trust store on start up..

I did this around two months back and dont have source code on me right now.. use google and you should be able to solve this problem. If you cant message me back and I can provide you the relevent source code for the project .. Dont know if this solves your problem since you havent provided the code which causes these exceptions. Furthermore I was working wiht applets thought I cant see why it wont work on Serverlets...

P.S I cant get source code before the weekend since external SSH is disabled in my office :(

Quarter answered 14/7, 2011 at 17:53 Comment(1)
P.S I found this java code online to extract and store the public keys of my server so keep googling or wait till sundayishQuarter
O
0

SSLHandshakeException can be resolved 2 ways.

  1. Incorporating SSL

    • Get the SSL (by asking the source system administrator, can also be downloaded by openssl command, or any browsers downloads the certificates)

    • Add the certificate into truststore (cacerts) located at JRE/lib/security

    • provide the truststore location in vm arguments as "-Djavax.net.ssl.trustStore="

  2. Ignoring SSL

    For this #2, please visit my other answer on another stackoverflow website: How to ingore SSL verification Ignore SSL Certificate Errors with Java

Ogden answered 16/3, 2017 at 2:4 Comment(0)
B
0

This is what I did to POST a JSON to a URL with insecure/invalid SSL certs using latest JDK 11 HttpClient:

    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
    };

    try {

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Creat HttpClient with new SSLContext.
        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofMillis(3 * 1000))
                .sslContext(sc) // SSL context 'sc' initialised as earlier
                .build();

        // Create request.
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(<URL>))
                .timeout(Duration.ofMinutes(1))
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(<PAYLOAD JSON STRING>))
                .build();

        //Send Request
        HttpResponse<String> response =
                httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        //Access response JSON
        String responseJson = response.body();

   } catch (Exception e) {
     throw new Exception(e);
   }
Bivins answered 31/10, 2022 at 9:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.